Allow feature builtins to overwrite existing builtins#13403
Conversation
0b7ac24 to
3957cf8
Compare
| assert!( | ||
| !self.is_frozen(), | ||
| "Can't change frozen bank by adding not-existing new native program ({}, {}). \ | ||
| Maybe, inconsistent program activation is detected on snapshot restore?", | ||
| name, | ||
| program_id | ||
| ); |
There was a problem hiding this comment.
Could you move this assertion to reside immediately before store_account? This assertion is tightly associated to store_account. We can safely assert!(!self.is_frozen()) even if must_replace is true. In general, we must not store_account once frozen in every conceivable situation. But that kind of protection isn't easy to add inside store_account itself, unfortunately. So, we're manually doing this because these activations deal with primitive arrangements with potentinal misbehavior of wracking frozen (snapshot) banks incorrectly.
So, the change hunk could be changed to look like this:
if must_replace {
assert!(already_genuine_program_exists, ...)
} else if already_genuine_program_exists {
return;
}
assert!(!self.is_frozen(), ...);
self.store_account(...);There was a problem hiding this comment.
@ryoqun Moving this assert breaks a bunch of snapshot tests once a NewVersion builtin is added. What do you recommend?
There was a problem hiding this comment.
@CriesofCarrots Blame me, I completely forget that this fn must retain idempotent of AccountsDB; so more subtle adjustment was needed: 2a9ff42 Hope this commit explains well. If still not sure, please say so. I'll update the in-source comment.
Sorry for confusing you because of my unreadable code. ;)
|
Thanks for working on this! Good progress. In addition to |
3957cf8 to
b896705
Compare
ryoqun
left a comment
There was a problem hiding this comment.
lgtm with a nit
Thanks for improving the native program initialization mechanism!
b896705 to
ec49a46
Compare
Codecov Report
@@ Coverage Diff @@
## master #13403 +/- ##
=========================================
- Coverage 81.9% 81.9% -0.1%
=========================================
Files 376 376
Lines 88308 88356 +48
=========================================
+ Hits 72345 72382 +37
- Misses 15963 15974 +11 |
|
automerge label removed due to a CI failure |
* Allow feature builtins to overwrite existing builtins * Add feature_builtin ActivationType * Correctly retain idempotent for replacing case * Fix test Co-authored-by: Ryo Onodera <ryoqun@gmail.com> (cherry picked from commit bc62313) # Conflicts: # ledger/src/builtins.rs # runtime/src/bank.rs
* Allow feature builtins to overwrite existing builtins * Add feature_builtin ActivationType * Correctly retain idempotent for replacing case * Fix test Co-authored-by: Ryo Onodera <ryoqun@gmail.com> (cherry picked from commit bc62313)
| // When replacing native_program, name must change to disambiguate from repeated | ||
| // invocations. |
There was a problem hiding this comment.
I think we should put a comment about this in builtins.rs, since it's critical to know when constructing the name
* Allow feature builtins to overwrite existing builtins * Add feature_builtin ActivationType * Correctly retain idempotent for replacing case * Fix test Co-authored-by: Ryo Onodera <ryoqun@gmail.com> (cherry picked from commit bc62313) Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
…3419) * Allow feature builtins to overwrite existing builtins (#13403) * Allow feature builtins to overwrite existing builtins * Add feature_builtin ActivationType * Correctly retain idempotent for replacing case * Fix test Co-authored-by: Ryo Onodera <ryoqun@gmail.com> (cherry picked from commit bc62313) # Conflicts: # ledger/src/builtins.rs # runtime/src/bank.rs * Fix conflicts Co-authored-by: Tyera Eulberg <teulberg@gmail.com> Co-authored-by: Tyera Eulberg <tyera@solana.com>
| let mut existing_genuine_program = self.get_account(&program_id); | ||
| if let Some(account) = &mut existing_genuine_program { | ||
| if !native_loader::check_id(&account.owner) { | ||
| // malicious account is pre-occupying at program_id | ||
| // forcibly burn and purge it |
There was a problem hiding this comment.
well this logic changes introduced a regression where we could be tricked into skipping to create native program because existing_genuine_program can be set to a bad account and not reset and we enters this match arm returning from this fn: https://github.com/solana-labs/solana/pull/13403/files#diff-ed47b4a0198313377e091bb3957bbbc63d937805426d1b2b6de39d0a50d32a0cR1760
Fixed and test is imrproved at #13884.
| ); | ||
|
|
||
| // Add a bogus executable native account, which will be loaded and ignored. | ||
| let account = native_loader::create_loadable_account(name); |
There was a problem hiding this comment.
Also, when replacing, we must consider the balance of existing program account otherwise we would cause capitalization mismatch if the replaced native program isn't 1 lamports.
Fixed and test added at #13884.
Problem
Right now, there is no easy way to redeploy a native program (to fix issues, eg). One appealing approach would be to deploy the updated program using feature_builtins, but this requires a way to overwrite an active builtin.
Summary of Changes
ensure_feature_builtinsto allow a feature_builtin to replace an existing builtinNeeded for #13394